﻿//LogSourceNode.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Xaml
{
	using System;
	using System.Collections.ObjectModel;
	using System.Collections.Specialized;
	using System.Linq;

	using Ecng.Collections;
	using Ecng.Common;
	using Ecng.Xaml;

	using StockSharp.Logging;

	/// <summary>
	/// Узел дерева источника логов.
	/// </summary>
	public class LogSourceNode : Disposable
	{
		private readonly ILogSourceNodeModel _model;

		/// <summary>
		/// Создать узел дерева стратегий.
		/// </summary>
		/// <param name="source">Источник логов.</param>
		/// <param name="model">Модель дерева источника логов.</param>
		public LogSourceNode(ILogSource source, ILogSourceNodeModel model)
		{
			if (source == null)
				throw new ArgumentNullException("source");

			if (model == null)
				throw new ArgumentNullException("model");

			Source = source;

			_model = model;

			ChildNodes = new ThreadSafeObservableCollection<LogSourceNode>();
			ChildNodes.CollectionChanged += OnChildNodesCollectionChanged;
		}

		private void OnChildSourcesCleared()
		{
			GuiDispatcher.GlobalDispatcher.AddSyncAction(() => ChildNodes.RemoveRange(ChildNodes.ToArray()));
		}

		private void OnChildSourcesRemoved(ILogSource s)
		{
			GuiDispatcher.GlobalDispatcher.AddSyncAction(() =>
			{
				var node = ChildNodes.First(n => n.Source == s);
				ChildNodes.Remove(node);
				node.Dispose();
			});
		}

		private void OnChildSourcesAdded(ILogSource s)
		{
			GuiDispatcher.GlobalDispatcher.AddSyncAction(() =>
			{
				//MUH: Могли уже добавить по WriteMessage
				if (ChildNodes.Any(n => n.Source == s))
					return;

				var node = _model.CreateNode(s);
				ChildNodes.Add(node);
			});
		}

		private void OnChildNodesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
		{
			if (e.NewItems != null)
			{
				foreach (LogSourceNode node in e.NewItems)
				{
					node.ParentNode = this;
					_model.NodeAdded(node);
				}
			}

			if (e.OldItems != null)
			{
				foreach (LogSourceNode node in e.OldItems)
				{
					_model.NodeRemoved(node);
				}
			}
		}

		/// <summary>
		/// Источник логов.
		/// </summary>
		public ILogSource Source { get; private set; }

		private LogSourceNode _parentNode;

		/// <summary>
		/// Родительский узел.
		/// </summary>
		public LogSourceNode ParentNode
		{
			get { return _parentNode; }
			private set
			{
				_parentNode = value;

				if (Source.Childs == null)
					return;

				foreach (var s in Source.Childs)
					OnChildSourcesAdded(s);

				Source.Childs.Added += OnChildSourcesAdded;
				Source.Childs.Removed += OnChildSourcesRemoved;
				Source.Childs.Cleared += OnChildSourcesCleared;
			}
		}

		/// <summary>
		/// Дочерние узлы.
		/// </summary>
		public ObservableCollection<LogSourceNode> ChildNodes { get; private set; }

		/// <summary>
		/// Освободить ресурсы.
		/// </summary>
		protected override void DisposeManaged()
		{
			ChildNodes.CollectionChanged -= OnChildNodesCollectionChanged;

			if (Source.Childs != null)
			{
				Source.Childs.Added -= OnChildSourcesAdded;
				Source.Childs.Removed -= OnChildSourcesRemoved;
				Source.Childs.Cleared -= OnChildSourcesCleared;
			}

			_parentNode = null;

			base.DisposeManaged();
		}

		/// <summary>
		/// Получить строковое представление узла.
		/// </summary>
		/// <returns>Строковое представление узла.</returns>
		public override string ToString()
		{
			return Source.Name;
		}
	}
}